#ifndef __MCS__FOR_ELEMENT__HPP
#define __MCS__FOR_ELEMENT__HPP

#include "Element.hpp"
#include "Block.hpp"
#include "Condition.hpp"
#include "ExpressionElement.hpp"
#include "TypeMismatchException.hpp"
#include "RunTimeException.hpp"

//! Executes C-style for-loop
class ForElement : public Element
{
public:
	ForElement(SourceLocation const & location, ptr<Element> init, ptr<Expression> cond, ptr<Element> step, ptr<Element> body)
		: Element(location)
		, innerBlock_(new Block(location))
		, initializer_(init)
		, condition_(new ForCondition(cond))
		, step_(step)
		, body_(body)
	{
		innerBlock_->appendElement(initializer_);
		innerBlock_->appendElement(condition_);
		innerBlock_->appendElement(body_);
		innerBlock_->appendElement(step_);
	}

	virtual void init(Block * parentBlock)
	{
		Element::init(parentBlock);
		innerBlock_->init(parentBlock);
	}

	virtual void execute() const
	{
		initializer_->execute();

		while(condition_->check())
		{
			body_->execute();
			step_->execute();
		}
	}
private:
	class ForCondition : public Element
	{
	public:
		ForCondition(ptr<Expression> expr)
			: Element(expr->location())
			, condition_(expr)
		{}

		virtual void init(Block * parentBlock)
		{
			condition_.init(parentBlock);
		}

		virtual void execute() const {}

		bool check() const { return condition_.check(); }
	private:
		Condition condition_;
	};

	ptr<Block> innerBlock_;
	ptr<Element> initializer_;
	ptr<ForCondition> condition_;
	ptr<Element> step_;
	ptr<Element> body_;
};

#endif //__MCS__FOR_ELEMENT__HPP
